#include "ringBuffer.h"

#undef MIN
#define MIN(a,b) ((a) > (b)?(b):(a))

/*环形缓冲区相关结构体*/
struct ringBuf_t {
	volatile uint32_t r_head;/*缓冲区头部*/
	volatile uint32_t r_tail;/*缓冲区尾部*/
	uint32_t          usrLen;/*用户定义缓冲区的长度*/
	uint8_t           *pUsrBuf;/*指向用户定义缓冲区的指针*/
};

static inline bool is_power_of_2(uint32_t n);

static inline bool is_power_of_2(uint32_t n)
{
	return ((n != 0) && ((n & (n - 1)) == 0));
}

uint32_t RingBufInit(struct ringBuf_t **_ringBuf, uint8_t *pBuf, const uint32_t len)
{
	struct ringBuf_t *ringBuf = NULL;
	if(!is_power_of_2(len)) { return 0; }

	ringBuf = (struct ringBuf_t *)malloc(sizeof(struct ringBuf_t));
	if(!ringBuf)
	{
		return 0;
	}
	*_ringBuf = ringBuf;
	
	ringBuf->r_head = 0;
	ringBuf->r_tail = 0;
	if(pBuf)
	{
		ringBuf->pUsrBuf = pBuf;
	}
	else
	{
		ringBuf->pUsrBuf = NULL;
		ringBuf->pUsrBuf = (uint8_t *)malloc(len * sizeof(uint8_t));
		if(!ringBuf->pUsrBuf)
		{
			free(*_ringBuf);
			*_ringBuf = NULL;
			
			return 0;
		}
	}
	ringBuf->usrLen = len;
	memset(ringBuf->pUsrBuf,0,len);

	return 1;
}

uint32_t RingWriteDataToBuffer(struct ringBuf_t *ringBuf, const uint8_t *pBuf, const uint32_t len)
{
	if(ringBuf == NULL) { return 0; }
	if(pBuf == NULL) { return 0; }
	if(len == 0) { return 0; }
	//如果不能存下此帧，则舍弃
	if(len > ringBuf->usrLen - (ringBuf->r_tail - ringBuf->r_head)) { return 0; }

	//计算写入位置
	uint32_t off = ringBuf->r_tail & (ringBuf->usrLen - 1);
	/*
	*写入数据
	*如果剩余空间未跨首尾相接的地方，则一次写入，否则分两次写入
	*/
	uint32_t min = MIN(len, ringBuf->usrLen - off);
	memcpy(&(ringBuf->pUsrBuf[off]), pBuf, min);
	memcpy(&(ringBuf->pUsrBuf[0]), pBuf + min, len - min);
	ringBuf->r_tail += len;

	return 1;
}

uint32_t RingReadDataFromBuffer(struct ringBuf_t *ringBuf, uint8_t *pBuf, const uint32_t len, const uint32_t rdlen)
{
	if(ringBuf == NULL) { return 0; }
	if(pBuf == NULL) { return 0; }
	if(len == 0) { return 0; }
	//无数据可读
	if(ringBuf->r_tail == ringBuf->r_head) { return 0; }

	//获取可读数据长度
	uint32_t rd_len = ringBuf->r_tail - ringBuf->r_head;
	//如果可读数据长度大于要读取的长度，则读取指定长度，否则读取可读数据长度
	rd_len = rd_len > rdlen ? rdlen : rd_len ;
	//存在内存越界风险
	if(rd_len > len) { return 0; }

	uint32_t off = ringBuf->r_head & (ringBuf->usrLen - 1);
	/*
	*读取数据
	*如果剩余空间未跨首尾相接的地方，则一次读出，否则分两次读出
	*/
	uint32_t min = MIN(rd_len, ringBuf->usrLen - off);
	memcpy(pBuf, &(ringBuf->pUsrBuf[off]), min);
	memcpy(pBuf + min, &(ringBuf->pUsrBuf[0]), rd_len - min);
	ringBuf->r_head += rd_len;

	return rd_len;
}

void RingBufDestroy(struct ringBuf_t *ringBuf)
{
	free(ringBuf->pUsrBuf);
	ringBuf->pUsrBuf = NULL;
	free(ringBuf);
	ringBuf = NULL;
}
